package algo3c3g5;

import algo3c3g5.componentes.*;
import algo3c3g5.componentes.Componente.TipoComponente;

import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;

//REGLA80Carcteres_0123456789012345678901234567890123456789012345678901234567890
public class Auto {

	private int id_duenio;
	private Map<TipoComponente, Componente> listComp;

	
	public Auto(int id) {
	
		this.id_duenio = id;
		this.listComp =	new HashMap<TipoComponente, Componente>();
		for (TipoComponente tipoComponente : TipoComponente.values())
			this.listComp.put(tipoComponente, null);

	}

	public void agregarComponente(Componente comp) {
		
		//(!)en esta logica si existe el componente es reemplazado
		this.listComp.put(comp.getTipoComponente(), comp);
		
		//logica de enlace interno
		if (comp.getTipoComponente() == TipoComponente.CARBURADOR) {
			((Carburador) comp).setTanqueDeCombustible(
					(TanqueDeCombustible) this.listComp.get(
							TipoComponente.TANQUE_DE_COMBUSTIBLE));
			//
			if (this.listComp.get(TipoComponente.MOTOR) != null) {
				((Motor) this.listComp.get(TipoComponente.MOTOR))
					.setCarburador((Carburador) comp);
			}
			//
		} else if(comp.getTipoComponente() == 
				TipoComponente.TANQUE_DE_COMBUSTIBLE) {
			if (this.listComp.get(TipoComponente.CARBURADOR) != null) {
				((Carburador) this.listComp.get(TipoComponente.CARBURADOR))
					.setTanqueDeCombustible((TanqueDeCombustible) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.ESCAPE) {
			if (this.listComp.get(TipoComponente.MOTOR) != null) {
				((Motor) this.listComp.get(TipoComponente.MOTOR))
					.setEscape((Escape) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.MOTOR) {
			((Motor) comp).setCarburador(
					(Carburador) this.listComp.get(TipoComponente.CARBURADOR));
			((Motor) comp)
				.setEscape((Escape) this.listComp.get(TipoComponente.ESCAPE));
			if (this.listComp.get(TipoComponente.CAJA_DE_CAMBIOS) != null) {
				((CajaDeCambios) this.listComp.get(
					TipoComponente.CAJA_DE_CAMBIOS)).setMotor((Motor) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.CAJA_DE_CAMBIOS) {
			((CajaDeCambios) comp).setMotor(
				(Motor) this.listComp.get(TipoComponente.MOTOR));
			if (this.listComp.get(TipoComponente.TRANSMISION) != null) {
				((Transmision) this.listComp.get(
					TipoComponente.TRANSMISION))
					.setCajaDeCambios((CajaDeCambios) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.TRANSMISION) {
			((Transmision) comp).setCajaDeCambios(
				(CajaDeCambios) this.listComp
				.get(TipoComponente.CAJA_DE_CAMBIOS));
			if (this.listComp.get(TipoComponente.DIFERENCIAL) != null) {
				((Diferencial) this.listComp.get(TipoComponente.DIFERENCIAL))
					.setTransmision((Transmision) comp);
					
			}
		} else if(comp.getTipoComponente() == TipoComponente.DIFERENCIAL) {
			((Diferencial) comp).setTransmision(
				(Transmision) this.listComp.get(TipoComponente.TRANSMISION));
			if (this.listComp.get(TipoComponente.LLANTAS) != null) {
				((Llantas) this.listComp.get(TipoComponente.LLANTAS))
					.setDiferencial((Diferencial) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.LLANTAS) {
			((Llantas) comp).setDiferencial(
				(Diferencial) this.listComp.get(TipoComponente.DIFERENCIAL));
			if (this.listComp.get(TipoComponente.NEUMATICOS) != null) {
				((Neumaticos) this.listComp.get(TipoComponente.LLANTAS))
					.setLlantas((Llantas) comp);
			}
		} else if(comp.getTipoComponente() == TipoComponente.NEUMATICOS) {
			((Neumaticos) comp).setLlantas(
				(Llantas) this.listComp.get(TipoComponente.LLANTAS));
		}
		

	}
	
	public Componente verComponente(TipoComponente tipoComponente) {
		
		return  this.listComp.get(tipoComponente);
		
	}
	
	public Componente removerComponente(TipoComponente tipoComponente) {
	
		Componente compARet = this.listComp.get(tipoComponente);
		this.listComp.put(tipoComponente, null);
		return compARet;
		
	}
	
	public boolean estaCompleto() {
		
		boolean completo = true;
		Iterator it = this.listComp.entrySet().iterator();
		while (it.hasNext()) {
			Componente comp = 
				(Componente) (((Map.Entry) it.next()).getValue());
			if (comp == null) {
				completo = false;
				break;
			}
		}
	
		return completo;
			
	}
	
	public boolean estaOperativo() {
		
		boolean operativo = true;
		Iterator it = this.listComp.entrySet().iterator();
		while (it.hasNext()) {
			Componente comp = 
				(Componente) (((Map.Entry) it.next()).getValue());
			if (!comp.estaOperativo()) {
				operativo = false;
				break;
			}
		}
		return operativo;
		
	}
	
	public double obtenerAceleracion(double coeficientePista, 
			double velocidad) {
	
		double aceleracion;
		
		//obtengo todas las fuerzas involucradas
		//dispara la secuencia de comunicacion entre componentes
		//(!)version inicial necesitara varios ajustes
		Neumaticos neumaticos = 
			(Neumaticos) this.listComp.get(TipoComponente.NEUMATICOS);
		double fuerzaVehiculoPista = neumaticos.obtenerFuerza() * 
			coeficientePista;
		//(!)esto esta pensado para tomar datos de la carroceria
		//tambien deberia haber un deglose mas fino de fuerza
		//por masa y rozamiento con el terreno
		double fuerzaResistAire = -(1/2) * velocidad * velocidad;
		
		aceleracion = (fuerzaVehiculoPista + fuerzaResistAire) * 
			this.getMasaTotal();
		
		return aceleracion;
		
	}
	
	private double getMasaTotal() {
		
		double masaAcumulada = 0;
		Iterator it = this.listComp.entrySet().iterator();
		while (it.hasNext()) {
			Componente comp = 
				(Componente) (((Map.Entry) it.next()).getValue());
			masaAcumulada = masaAcumulada + comp.getMasa();
		}
	
		return masaAcumulada;
		
	}
	
	public double combustibleDisponible() {
		
		double combustibleDisponible = 0;
		TanqueDeCombustible tanque = 
			(TanqueDeCombustible) this.listComp.get(
			TipoComponente.TANQUE_DE_COMBUSTIBLE);
		if (tanque != null)	{
			combustibleDisponible = tanque.combustibleDisponible();
		}
		return combustibleDisponible;
		
	}
	
	public double llenarTanqueDeCombustible() {
		
		double cantCombustibleCargada = 0;
		TanqueDeCombustible tanque = 
			(TanqueDeCombustible) this.listComp.get(
			TipoComponente.TANQUE_DE_COMBUSTIBLE);
		if (tanque != null)	{
			if (tanque.estaOperativo()) {
				cantCombustibleCargada = tanque.llenar();
			}
		}
		return cantCombustibleCargada;
		
	}
	
	public boolean acelerar(double porcent) {
		
		boolean exito = false;
		//(!)no se puede indicar menos del 10%
		if (porcent >= 10 && porcent <= 100 ) {
			Carburador carburador = 
				(Carburador) this.listComp.get(TipoComponente.CARBURADOR);
			if (carburador != null) {
				if (carburador.estaOperativo()) {
					carburador.setPorcentCombustMezcla(porcent);
					exito = true;
				}
			}
		}
		return exito;
		
	}
	
	public boolean frenar(double cant){
		
		//(!)implementar
		return true;
		
	}
	
	public void encender() {
		
		((Motor) this.listComp.get(TipoComponente.MOTOR)).encender();
		
	}
	
	public void detener() {
		
		((Motor) this.listComp.get(TipoComponente.MOTOR)).detener();
		
	}
	
	public boolean estaEncendido() {
	
		return ((Motor) this.listComp
				.get(TipoComponente.MOTOR)).estaEncendido();
		
	}
	
}